#ifndef _CANARY2_CORO_RETURN_VALUE_OR_VOID_H_
#define _CANARY2_CORO_RETURN_VALUE_OR_VOID_H_

#include <memory>
#include <atomic>
#include <concepts>

#include "data_propagator.h"
#include "awaker_concepts.h"

namespace wilson::coro
{
    struct return_value_base
    {
        void set_need_return() noexcept 
        { 
            m_data_propagator = ::std::make_shared<coro::data_propagator>(); 
        }

        bool need_return() noexcept{ return m_data_propagator != nullptr; }
        auto data_propagator() noexcept { return m_data_propagator; }

        ::std::shared_ptr<coro::data_propagator> m_data_propagator;
    };

    template<typename T, awaker Awk>
    struct _return_value_or_void 
    {
        struct _type : public return_value_base
        {
            template<typename Value = T>
            requires (
                ::std::convertible_to<Value, T> && 
                ::std::constructible_from<T, Value>)
            void return_value(Value&& v)
            {
                if (m_data_propagator)
                    m_data_propagator->set_value(::std::forward<Value>(v));
            }
        };
    };

    template<awaker Awk>
    struct _return_value_or_void<void, Awk>
    {
        struct _type : public return_value_base
        {
            void return_void() 
            { 
                if (m_data_propagator)
                    m_data_propagator->set_value();
            }
        };
    };

    template<typename T, typename Awk>
    using return_value_or_void = 
        typename _return_value_or_void<T, Awk>::_type;
}

#endif
